{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<p style=\"text-align: center;font-size: 33px;font-weight:bold;\"> <span style=\"color:DarkGoldenrod\">&lt;&lt;输入、输出与文件访问&gt;&gt;</span></p>\n",
    "<p style=\"text-align: center;font-size: 25px;font-weight:bold;\"> <span style=\"color:Goldenrod\">&lt;&lt; IO AND FILE ACCESS  &gt;&gt;</span></p>\n",
    "<p style=\"text-align: right; font-size:15px; font-weight:normal\">----学而时习之，不亦乐乎？</p>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* **输入输出流**\n",
    "* **变长参数列表**\n",
    "* **文件指针与文件的打开模式**\n",
    "* **C程序隐含的文件指针**\n",
    "* **文件的二进制读写**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### **输入输出流**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "假设程序prog使用getchar(void)函数从**标准输入流**中获取信息，那么： <br>\n",
    "prog&lt;infile &nbsp;&nbsp;&nbsp;&nbsp; 将**输入流**重定向为infile文件 将<br>\n",
    "假设程序prog使用putchar(void)函数在**标准输出流**中打印信息，那么：  <br>\n",
    "prog&gt;outfile &nbsp;&nbsp;&nbsp;&nbsp; 将**输出流**重定向为outfile文件  <br>\n",
    "prog|prog1 &nbsp;&nbsp;&nbsp;&nbsp; 将prog的输出作为prog1的输入   <br>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### **变长参数列表**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#include <stdarg.h>\n",
    "//printf(\"%d,%s,%f\",11,\"abc\",3.13);\n",
    "/* minprintf: minimal printf with variable argument list */\n",
    "void minprintf(char *fmt, ...)\n",
    "{\n",
    "va_list ap; /* points to each unnamed arg in turn */\n",
    "char *p, *sval;\n",
    "int ival;\n",
    "double dval;\n",
    "va_start(ap, fmt); /* make ap point to 1st unnamed arg */\n",
    "for (p = fmt; *p; p++) {\n",
    "   if (*p != '%') {\n",
    "       putchar(*p);\n",
    "       continue;\n",
    "    }\n",
    "   switch (*++p) {\n",
    "     case 'd':\n",
    "     ival = va_arg(ap, int);\n",
    "     printf(\"%d\", ival);\n",
    "     break;\n",
    "     case 'f':\n",
    "     dval = va_arg(ap, double);\n",
    "     printf(\"%f\", dval);\n",
    "     break;\n",
    "     case 's':\n",
    "     for (sval = va_arg(ap, char *); *sval; sval++)\n",
    "         putchar(*sval);\n",
    "     break;\n",
    "     default:\n",
    "     putchar(*p);\n",
    "     break;\n",
    "    }\n",
    "   }\n",
    "va_end(ap); /* clean up when done */\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### **文件指针与文件的打开模式**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```C\n",
    "FILE* fp=NULL; //定义并初始化一个文件指针，初始化是一个好习惯。\n",
    "int main(){ //无参主函数。带参int main(int arc,char* argv[]) arc为参数个数，argv为参数列表\n",
    "fp=fopen(路径,模式); //模式='r','w','a','rb','wb','ab'(读，写，追加|二进制读写+b)\n",
    "    //...\n",
    "    //文件读写操作语句 \n",
    "    //...\n",
    "fclose(fp);//一定要记得关闭文件    \n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* **顺序读写字符示例：**\n",
    "* **代码1：显示文件内容**\n",
    "* **代码2：拷贝文件**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "# C课程jupyternotebooks\n",
      "\n",
      "#### 项目介绍\n",
      "用于教学的C语言jupyternotebooks\n",
      "\n",
      "#### 软件架构\n",
      "B-S 新型C语言教学环境\n",
      "#### 安装教程\n",
      "1. mybinder.org\n",
      "2. github\n",
      "3. 配置 environment.yml 以决定mybinder.org分配Docker容器的依赖关系\n",
      "4. 配置 postBuild 以启动jupyter extentisons并安装jupyter-c-kernel\n",
      "#### 使用说明\n",
      "1. 打开Jupyter-Notebook： \n",
      " * [课2](https://mybinder.org/v2/gh/hilhert/c_course_jupyter/master?filepath=Class2_pubc.ipynb)\n",
      " * [课3](https://mybinder.org/v2/gh/hilhert/c_course_jupyter/master?filepath=Class3_pubc.ipynb)\n",
      " * [课4](https://mybinder.org/v2/gh/hilhert/c_course_jupyter/master?filepath=Class4_pubc.ipynb)\n",
      " * [课5](https://mybinder.org/v2/gh/hilhert/c_course_jupyter/master?filepath=Class5_pubc.ipynb)\n",
      " * [课6](https://mybinder.org/v2/gh/hilhert/c_course_jupyter/master?filepath=Class6_pubc.ipynb)\n",
      " * [课7](https://mybinder.org/v2/gh/hilhert/c_course_jupyter/master?filepath=Class7_pubc.ipynb)\n",
      " * [课8](https://mybinder.org/v2/gh/hilhert/c_course_jupyter/master?filepath=Class8_pubc.ipynb)\n",
      " * [课9](https://mybinder.org/v2/gh/hilhert/c_course_jupyter/master?filepath=Class9_pubc.ipynb)\n",
      "2. 打开Jupyter-Lab: Jupyter-Notebook出现地址去掉`notebooks及以后`，添加`lab`回车\n",
      "3. 本人VPS上建立jupyter-hub的匿名访问:[连接2](http://45.76.192.159:8000)\n",
      "4. 当使用[连接2](http://45.76.192.159:8000)打开notebooks时，请打开新建一个终端(Terminal),然后键入`git clone https://github.com/hilhert/c_course_jupyter.git`即可获取本课程资源。\n",
      "\n"
     ]
    }
   ],
   "source": [
    "#include <stdio.h>\n",
    "FILE* fp=NULL;\n",
    "char c;\n",
    "int main(){\n",
    "fp=fopen(\"./README.md.cp1\",\"r\");  //fopen函数智能放在函数内部。\n",
    "    while ((c = getc(fp)) != EOF) //EOF end of file.\n",
    "      printf(\"%c\",c); printf(\"\\n\");\n",
    "fclose(fp);    \n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#include <stdio.h>\n",
    "FILE* fp=NULL;\n",
    "FILE* fp1=NULL;\n",
    "char c;\n",
    "int main(){\n",
    "fp=fopen(\"./README.md\",\"r\");  //fopen函数智能放在函数内部。\n",
    "fp1=fopen(\"./README.md.cp1\",\"w\"); //不需要创建文件，由w写模式与系统中是否存在文件决定文件是否自动创建。    \n",
    "    while ((c = getc(fp)) != EOF)  // getc 读一个字符（8））。\n",
    "      putc(c,fp1);\n",
    "fclose(fp1);\n",
    "fclose(fp);    \n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### **C隐含的文件指针**\n",
    "* **标准输出文件指针：stdout**\n",
    "* **标准输入文件指针：stdin**\n",
    "* **标准错误文件指针：stderr**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "# C课程jupyternotebooks\n",
      "\n",
      "#### 项目介绍\n",
      "用于教学的C语言jupyternotebooks\n",
      "\n",
      "#### 软件架构\n",
      "B-S 新型C语言教学环境\n",
      "#### 安装教程\n",
      "1. mybinder.org\n",
      "2. github\n",
      "3. 配置 environment.yml 以决定mybinder.org分配Docker容器的依赖关系\n",
      "4. 配置 postBuild 以启动jupyter extentisons并安装jupyter-c-kernel\n",
      "#### 使用说明\n",
      "1. 打开Jupyter-Notebook： \n",
      " * [课2](https://mybinder.org/v2/gh/hilhert/c_course_jupyter/master?filepath=Class2_pubc.ipynb)\n",
      " * [课3](https://mybinder.org/v2/gh/hilhert/c_course_jupyter/master?filepath=Class3_pubc.ipynb)\n",
      " * [课4](https://mybinder.org/v2/gh/hilhert/c_course_jupyter/master?filepath=Class4_pubc.ipynb)\n",
      " * [课5](https://mybinder.org/v2/gh/hilhert/c_course_jupyter/master?filepath=Class5_pubc.ipynb)\n",
      " * [课6](https://mybinder.org/v2/gh/hilhert/c_course_jupyter/master?filepath=Class6_pubc.ipynb)\n",
      " * [课7](https://mybinder.org/v2/gh/hilhert/c_course_jupyter/master?filepath=Class7_pubc.ipynb)\n",
      " * [课8](https://mybinder.org/v2/gh/hilhert/c_course_jupyter/master?filepath=Class8_pubc.ipynb)\n",
      " * [课9](https://mybinder.org/v2/gh/hilhert/c_course_jupyter/master?filepath=Class9_pubc.ipynb)\n",
      "2. 打开Jupyter-Lab: Jupyter-Notebook出现地址去掉`notebooks及以后`，添加`lab`回车\n",
      "3. 本人VPS上建立jupyter-hub的匿名访问:[连接2](http://45.76.192.159:8000)\n",
      "4. 当使用[连接2](http://45.76.192.159:8000)打开notebooks时，请打开新建一个终端(Terminal),然后键入`git clone https://github.com/hilhert/c_course_jupyter.git`即可获取本课程资源。\n"
     ]
    }
   ],
   "source": [
    "#include <stdio.h>\n",
    "FILE* fp=NULL;\n",
    "//FILE* fp1=NULL;\n",
    "char c;\n",
    "int main(){\n",
    "fp=fopen(\"./README.md\",\"r\");  //fopen函数智能放在函数内部。\n",
    "//fp1=fopen(\"./README.md.cp\",\"w\"); //不需要创建文件，由w写模式与系统中是否存在文件决定文件是否自动创建。    \n",
    "    while ((c = getc(fp)) != EOF) //EOF 代表：End of File\n",
    "      putc(c,stdout);   \n",
    "fclose(fp);    \n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* **scanf:    从stdin中格式化输入数据**\n",
    "* **printf:   从stdout中格式化输出数据**\n",
    "* **fscanf:   从任意文件流（指针）中格式化输入数据**\n",
    "* **fprintf:  从任意文件流（指针）中格式化输出数据**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### **文件的二进制读写**\n",
    "* **读写数组**\n",
    "* **读写结构体**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```C\n",
    "size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );\n",
    "size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );\n",
    "```\n",
    "\n",
    "\n",
    "ptr(0xabcd00FFFCC)  ->     (0xabcd00FFFC0)  _ _ _ _ _ _ _ _\n",
    "                           (0xabcd00FFFC1)  _ _ _ _ _ _ _ _\n",
    "                           (0xabcd00FFFC2)  _ _ _ _ _ _ _ _\n",
    "                           (0xabcd00FFFC3)  _ _ _ _ _ _ _ _\n",
    "                           ...........\n",
    "                           (0xabcd00FFFC2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* **写数组**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "#include <stdio.h>\n",
    "#include <stdlib.h>\n",
    "FILE * pFile=NULL;\n",
    "void main ()\n",
    "{\n",
    "  \n",
    "  int buffer[] = {1, 2, 3, 4};\n",
    "  if((pFile = fopen (\"integers1.txt\", \"wb\"))==NULL)\n",
    "  {\n",
    "      printf(\"cant open the file\");\n",
    "      exit(0);  //exit 与 return 的区别，exit可以出现在任何函数中\n",
    "  }\n",
    "  //可以写多个连续的数据(这里一次写4个)\n",
    "  fwrite (buffer , sizeof(int), 4, pFile);  //\n",
    "  fclose (pFile);\n",
    "  //return 0;\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* **读数组**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n",
      "4\n"
     ]
    }
   ],
   "source": [
    "#include <stdio.h>\n",
    "#include <stdlib.h>\n",
    "FILE * fp=NULL;\n",
    "void  main () {\n",
    "     \n",
    "    int buffer[4];\n",
    "    if((fp=fopen(\"integers1.txt\",\"rb\"))==NULL)  //binary\n",
    "    {\n",
    "      printf(\"cant open the file\");\n",
    "      exit(0);\n",
    "    }\n",
    "    if(fread(buffer,sizeof(int),4,fp)!=4)   //可以一次读取\n",
    "    {\n",
    "        printf(\"file read error\\n\");\n",
    "        exit(1);  //不同代码段给出不同标号，方便调试\n",
    "    }\n",
    "\n",
    "    for(int i=0;i<4;i++)\n",
    "        printf(\"%d\\n\",buffer[i]);\n",
    "    fclose(fp);\n",
    "   // return 0;\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* **写结构体**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "#include <stdio.h>\n",
    "#include <string.h>\n",
    "#include <stdlib.h>\n",
    "typedef struct{\n",
    "    int age;\n",
    "    char name[30];\n",
    "} People;    \n",
    "\n",
    "FILE * pFile=NULL;\n",
    "int i;\n",
    "\n",
    "void main ()\n",
    "{\n",
    "    People p[3];    // p  数组首地址。  函数栈区的内存。  \n",
    "    p[0].age=20,strcpy(p[0].name,\"li\");\n",
    "    p[1].age=18,strcpy(p[1].name,\"wang\");\n",
    "    p[2].age=21,strcpy(p[2].name,\"zhang\");\n",
    "\n",
    "    if((pFile = fopen (\"structs1.txt\", \"wb\"))==NULL)\n",
    "    {\n",
    "        printf(\"cant open the file\");\n",
    "        exit(0);\n",
    "    }\n",
    "\n",
    "    if(fwrite(p,sizeof(People),3,pFile)!=3)\n",
    "        printf(\"file write error\\n\");\n",
    "    \n",
    "    fclose (pFile);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* **读结构体**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "20 li\n",
      "18 wang\n",
      "21 zhang\n"
     ]
    }
   ],
   "source": [
    "#include <stdio.h>\n",
    "#include <string.h>\n",
    "#include <stdlib.h>\n",
    "#include <malloc.h>\n",
    "typedef struct{\n",
    "    int age;\n",
    "    char name[30];\n",
    "} People;\n",
    "\n",
    "FILE * fp;\n",
    "People* p=NULL;\n",
    "   \n",
    "void main () {\n",
    "    p=(People*) malloc(sizeof(People));// 为p申请内存空间\n",
    "    if((fp=fopen(\"structs1.txt\",\"rb\"))==NULL)\n",
    "    {\n",
    "      printf(\"cant open the file\");\n",
    "      exit(0);\n",
    "    }\n",
    "    while(fread(p,sizeof(People),1,fp)==1)   //如果读到数据，就显示；否则退出\n",
    "    {\n",
    "        printf(\"%d %s\\n\",p->age,p->name);\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "//非线性递归。\n",
    "//函数的递归调用，汉诺塔！  非线性递归，或者说树形递归。\n",
    "#include <stdio.h>\n",
    "void hanoi(int disks,char from,char to,char temp){\n",
    "if(disks==1) {\n",
    "printf(\"put disk from %c to %c\\n\", from,to);\n",
    "return;\n",
    "}\n",
    "hanoi(disks-1,from,temp,to);  //将98个圆盘从A移动到B \n",
    "printf(\"put disk from %c to %c\\n\", from,to);//老和尚将最底下的圆盘从A移动到C\n",
    "hanoi(disks-1,temp,to,from);  //将98个圆盘从B移动到C  \n",
    "}\n",
    "int main(){\n",
    "    hanoi(99,'A','C','B');\n",
    "}\n",
    "// 将99层汉若塔问题胡解题步骤写到文件 hanoi.txt 中。 \n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "C",
   "language": "c",
   "name": "c"
  },
  "language_info": {
   "file_extension": ".c",
   "mimetype": "text/plain",
   "name": "c"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
